package com.mamba.microservice.http;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.Consts;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.config.*;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.impl.client.*;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.nio.charset.CodingErrorAction;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

/**
 * Copyright ©2020 360jinrong All Rights Reserved
 * 请添加类/接口的说明：
 *
 * @Package: com.qihoo.finance.utils.http.crawler
 * @author: fangjin
 * @date: 2020年04月15日 14时21分
 */
public class HttpClientComponentBuilder {
    protected static final Logger logger = LoggerFactory.getLogger(HttpClientComponentBuilder.class);
    private HttpClientBuilder httpClientBuilder = HttpClients.custom();

    /**
     * 创建普通的客户端
     *
     * @return
     */
    public HttpClientComponentBuilder createHttpClient() {
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
        setConnectionManagerParams(connectionManager);
        httpClientBuilder.setConnectionManager(connectionManager);
        return this;
    }

    /**
     * 创建Https客户端
     *
     * @return
     */
    public HttpClientComponentBuilder createHttpsClient() {
        try {
            SSLContext sslContext = SSLContexts.custom().useTLS().build();
            sslContext.init(null, new TrustManager[]{new X509TrustManager() {

                @Override
                public void checkClientTrusted(X509Certificate[] arg0, String arg1)
                        throws CertificateException {
                }

                @Override
                public void checkServerTrusted(X509Certificate[] arg0, String arg1)
                        throws CertificateException {
                }

                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
            }}, null);
            Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                    .register("http", PlainConnectionSocketFactory.INSTANCE)
                    .register("https", new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE))
                    .build();
            PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
            setConnectionManagerParams(connectionManager);

            httpClientBuilder.setConnectionManager(connectionManager);
            return this;
        } catch (Exception e) {
            logger.error("创建https客户端失败", e);
            return null;
        }
    }

    /**
     * 设置cookie
     *
     * @param basicCookieStore
     * @return
     */
    public HttpClientComponentBuilder setCookies(BasicCookieStore basicCookieStore) {
        httpClientBuilder.setDefaultCookieStore(basicCookieStore);
        return this;
    }

    /**
     * 设置代理
     *
     * @param proxy
     * @return
     */
    public HttpClientComponentBuilder setProxy(HttpProxy proxy) {
        if (null != proxy) {
            HttpHost proxyHost = new HttpHost(proxy.getHost(), proxy.getPort());
            CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
            if (StringUtils.isNotEmpty(proxy.getHost()) && StringUtils.isNotEmpty(proxy.getPassword())) {
                credentialsProvider.setCredentials(new AuthScope(proxy.getHost(), proxy.getPort()),
                        new UsernamePasswordCredentials(proxy.getUser(), proxy.getPassword()));
            }
            httpClientBuilder.setProxy(proxyHost).setDefaultCredentialsProvider(credentialsProvider);
        }
        return this;
    }

    /**
     * 生成客户端
     *
     * @return
     */
    public CloseableHttpClient build() {
        return httpClientBuilder.build();
    }


    /**
     * 设置连接池的参数
     */
    private void setConnectionManagerParams(PoolingHttpClientConnectionManager connectionManager) {
        SocketConfig socketConfig = SocketConfig.custom().setTcpNoDelay(true).build();
        connectionManager.setDefaultSocketConfig(socketConfig);
        MessageConstraints messageConstraints = MessageConstraints.custom().setMaxHeaderCount(200)
                .setMaxLineLength(2000).build();
        ConnectionConfig connectionConfig = ConnectionConfig.custom()
                .setMalformedInputAction(CodingErrorAction.IGNORE)
                .setUnmappableInputAction(CodingErrorAction.IGNORE).setCharset(Consts.UTF_8)
                .setMessageConstraints(messageConstraints).build();
        connectionManager.setDefaultConnectionConfig(connectionConfig);
        connectionManager.setMaxTotal(200);
        connectionManager.setDefaultMaxPerRoute(20);
    }

}
